package org.su.webadapter;


import com.google.protobuf.GeneratedMessageLite;
import com.google.protobuf.Message;
import org.su.generalmvc.IEditor;
import org.su.generalmvc.IModel;
import org.su.generalmvc.IParamBinder;
import org.su.generalmvc.annotaion.ContentType;
import org.su.generalmvc.bind.RequestEditor;
import org.su.generalmvc.bind.ResponseEditor;
import org.su.generalmvc.entity.FormFile;
import org.su.generalmvc.jdbc.IDao;
import org.su.generalmvc.validate.Errors;
import org.su.webadapter.bind.*;
import org.su.webadapter.validate.ValidateErrors;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * 数据绑定管理类，只在初始化时使用
 * 
 * @author xkliu
 * 
 */
public class WebDataBinder implements IParamBinder{
	
	private static final WebDataBinder instence = new WebDataBinder();
	
	public Map<Class<?>, IEditor> editors = new HashMap<Class<?>, IEditor>();
	public BeanEditor beanEditor = new BeanEditor();
	public ArrayBeanEditor beansEditor = new ArrayBeanEditor();
    public PMessageEditor messageEditor = new PMessageEditor();

	/**
	 * 标记类型为java基本原始类型,告知扫描器在扫描到这些类型的时候,不必下钻其属性扫描。
     */
	private HashSet<Class<?>> atomicContext = new HashSet<>();

	public WebDataBinder() {
		initBinder();
	}

	public static WebDataBinder getInstence(){
		return instence;
	}
	
	public IEditor findEditor(Class<?> type) {
		IEditor result = editors.get(type);

		if (result == null) {
			if(type.isArray() || Collection.class.isAssignableFrom(type)){
				result = beansEditor;
			}else {
				result = Message.class.isAssignableFrom(type) || GeneratedMessageLite.class.isAssignableFrom(type) ? messageEditor : beanEditor;
			}
		}

		return result;
	}

    @Override
    public boolean isCustomEditor(IEditor editor) {
        return beanEditor.equals(editor) || messageEditor.equals(editor) ||beansEditor.equals(editor);
    }

	@Override
	public boolean isBaseEditor(Class<?> type) {
		return type.getPackage().getName().startsWith("java.") || atomicContext.contains(type);
	}

	/**
	 * 绑定编辑器，可根据需要扩展自己的编辑器，通过该方法注入到系统框架上。
	 * @param clazz 类型
	 * @param editor 编辑器
	 */
	public void bind(Class<?> clazz, IEditor editor){
		editors.put(clazz,editor);
	}
	
	public void initBinder() {
		editors.put(String.class, new StringEditor());
		//atomicContext.add(String.class);
		editors.put(Timestamp.class, new TimestampEditor());
		//atomicContext.add(Timestamp.class);
		editors.put(java.util.Date.class, new DateEditor());
		//atomicContext.add(java.util.Date.class);
		editors.put(java.sql.Date.class, new SqlDateEditor());
		//atomicContext.add(java.sql.Date.class);
		editors.put(java.sql.Time.class, new TimeEditor());
		//atomicContext.add(java.sql.Time.class);

		editors.put(HttpServletRequest.class, new RequestEditor());
		editors.put(HttpServletResponse.class, new ResponseEditor());
        editors.put(ServletRequest.class, new RequestEditor());
        editors.put(ServletResponse.class, new ResponseEditor());
		editors.put(HttpSession.class, new SessionEditor());

		editors.put(Byte.TYPE, new AtomicByteEditor());
		editors.put(Long.TYPE, new AtomicLongEditor());
		editors.put(Double.TYPE, new AtomicDoubleEditor());
		editors.put(Float.TYPE, new AtomicFloatEditor());
		editors.put(Short.TYPE, new AtomicShortEditor());
		editors.put(Integer.TYPE, new AtomicIntegerEditor());
		editors.put(Boolean.TYPE, new BooleanEditor());
		editors.put(Character.TYPE,new CharEditor());
		

		editors.put(Byte.class, new ByteEditor());
		//atomicContext.add(Byte.class);
		editors.put(Long.class, new LongEditor());
		//atomicContext.add(Long.class);
		editors.put(Double.class, new DoubleEditor());
		//atomicContext.add(Double.class);
		editors.put(Float.class, new FloatEditor());
		//atomicContext.add(Float.class);
		editors.put(Short.class, new ShortEditor());
		//atomicContext.add(Short.class);
		editors.put(Integer.class, new IntegerEditor());
		//atomicContext.add(Integer.class);
		editors.put(Boolean.class, new BooleanEditor());
		//atomicContext.add(Boolean.class);
		editors.put(BigDecimal.class, new BigDecimalEditor());
		//atomicContext.add(BigDecimal.class);

		/** **********数组类型***************** */
		editors.put((new String[0]).getClass(), new ArrayParamEditor<String>(
				String.class, findEditor(String.class)));
		editors.put((new Integer[0]).getClass(), new ArrayParamEditor<Integer>(
				Integer.class, findEditor(Integer.class)));
		editors.put((new Long[0]).getClass(), new ArrayParamEditor<Long>(
				Long.class, findEditor(Long.class)));
		editors.put((new Double[0]).getClass(), new ArrayParamEditor<Double>(
				Double.class, findEditor(Double.class)));
		editors.put((new Float[0]).getClass(), new ArrayParamEditor<Float>(
				Float.class, findEditor(Float.class)));
		editors.put((new Short[0]).getClass(), new ArrayParamEditor<Short>(
				Short.class, findEditor(Short.class)));
		editors.put((new Byte[0]).getClass(), new ArrayParamEditor<Byte>(
				Byte.class, findEditor(Byte.class)));
		
		
		
		editors.put((new int[0]).getClass(), new ArrayAIntParamEditor());
		editors.put((new long[0]).getClass(), new ArrayALongParamEditor());
		editors.put((new double[0]).getClass(), new ArrayADoubleParamEditor());
		editors.put((new float[0]).getClass(), new ArrayAFloatParamEditor());
		editors.put((new short[0]).getClass(), new ArrayAShortParamEditor());
		editors.put((new byte[0]).getClass(), new ArrayAByteParamEditor());
		editors.put((new char[0]).getClass(), new ArrayACharParamEditor());

		
		editors.put((new FormFile[0]).getClass(), new ArrayFormFileEditor());
		/**************************************************
		 * 
		 */
		editors.put(ContentType.json.getClass(),new JsonEditor());
		editors.put(FormFile.class, new FormFileEditor());
		editors.put(IDao.class, new DAOEditor());
		editors.put(Errors.class, new ErrorsEditor());
		editors.put(IModel.class, new ErrorsEditor());
		editors.put(ValidateErrors.class, new ValidateErrorsEditor());
	}


public static void main(String[] args){
	WebDataBinder webDataBinder = new WebDataBinder();
	System.out.println(webDataBinder.isBaseEditor(String.class));

}
}
